package com.nx.platform.openentry.server;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.nx.arch.nxrpc.client.support.SCFClientMethodSignatureKeyGenerator;
import com.nx.platform.openentry.annotation.parser.AnnotationScan;
import com.nx.platform.openentry.contract.ICmdRouterService;
import com.nx.platform.openentry.entity.*;
import com.nx.platform.openentry.system.ParamDefaultValue;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * @author alex
 * @brief
 * @date 2019/11/29
 */
@Slf4j
public class DefaultRouterServiceImpl implements ICmdRouterService {
    protected SCFClientMethodSignatureKeyGenerator methodSignatureKeyGenerator = new SCFClientMethodSignatureKeyGenerator();

    /**
     * @param header   封装通用参数，包括logStr，当前访问者的uid，用户的设备信息，微服务调用链深度等
     * @param paramMap http协议的get post 参数
     * @return
     */

    @Override
    public CmdRouterResponse process(ServiceHeaderEntity header, Map<String, String> paramMap) throws Exception {
        AnnotationScan.initAnnotation();
        if (header == null) {
            CmdRouterResponse r = new CmdRouterResponse();
            r.setRetCode(-1);
            return r;
        }
        MethodEntity methodEntity = null;
        try {
            log.info("desc=DefaultCmdRouterService header={} params={}", JSON.toJSONString(header), JSON.toJSONString(paramMap));
            Map<String, MethodEntity> mapCommonEntry = AnnotationScan.getMapCommonEntry();
            methodEntity = mapCommonEntry.get(header.getCmd());

            CmdRouterResponse r = new CmdRouterResponse();
            if (methodEntity == null) {
                log.error("{} desc=method_not_register action=check_annotation", header.getLogStr());
                r.setRetCode(-1);
                r.setErrorMsg("服务端未注册正确");
                return r;
            }
            List<Object> paramValues = Lists.newArrayList();
            for (ParamEntity param : methodEntity.getParams()) {
                Object paramValue = null;
                String value = paramMap.get(param.getParamName());
                // 如果是基本数据类型，并且为null，直接设置默认值
                if (value == null && param.getParamClass().isPrimitive()) {
                    value = ParamDefaultValue.getDefaultValue(param.getParamClass()).toString();
                }
                if (String.class.equals(param.getParamClass())) {
                    paramValue = value;
                } else {
                    try {
                        paramValue = JSON.parseObject(value, param.getParamClass());
                    } catch (Exception e) {
                        log.error("{DefaultCmdRouterService}参数异常header:{},params:{},methodEntity:{},fromValue:{},toParamClass:{}",
                                header, JSON.toJSONString(paramMap), methodEntity, value, param.getParamClass());
                        r.setRetCode(415);
                        r.setErrorMsg("参数异常");
                        return r;
                    }
                }
                paramValues.add(paramValue);
            }
            Method method = methodEntity.getMethod();
            Object result = method.invoke(methodEntity.getObj(), paramValues.toArray());

            if (result instanceof RpcBaseResult) {
                RpcBaseResult<?> baseResult = (RpcBaseResult<?>) result;
                if (baseResult.getCode() == 0) {
                    r.setRetCode(baseResult.getCode());
                    r.setRetBody(JSON.toJSONString(baseResult.getData()));
                    r.setErrorMsg(baseResult.getErrorMsg());
                    // 设置cookie
                    r.setCookieValue(baseResult.getCookieValue());
                    if (baseResult.getContentType() != null) {
                        r.setContentType(baseResult.getContentType());
                    } else {
                        r.setContentType(CmdRouterResponse.CONTENT_TYPE_JSON);
                    }
                    r.setStreamData(baseResult.getStreamData());
                } else {
                    r.setRetCode(baseResult.getCode());
                    r.setErrorMsg(baseResult.getErrorMsg());
                }
            } else {
                r.setRetCode(0);
                r.setRetBody(JSON.toJSONString(result));
            }
            return r;
        } catch (Exception e) {
            log.error("{DefaultCmdRouterService},header:{} error={}", header, e);

            throw new Exception(e);
        }
    }
}
